/* The file is saved in UTF-8 codepage.
 * Check: «Stereotype», Section mark-§, Copyright-©, Alpha-α, Beta-β, Smile-☺
 */
package cz.pecinovsky.english.lootp._134_;

import cz.pecinovsky.english.lootp.manager.CanvasManager_Envelope.CanvasManager;
import cz.pecinovsky.english.lootp.manager.IPaintable;
import cz.pecinovsky.english.lootp.manager.Painter;
import cz.pecinovsky.english.lootp.manager.Rectangle;

import cz.pecinovsky.english.lootp._134_.Ring_134_.Ring;


//import cz.pecinovsky.english.lootp._134_.Town_134_        .Town;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ End of ignored starting test - place for imports +++++
//%I+ >=132z
//
//import cz.pecinovsky.english.lootp.canvasmanager.IPaintable;
//import cz.pecinovsky.english.lootp.canvasmanager.Painter;
//import cz.pecinovsky.english.lootp.canvasmanager.Rectangle;
//import cz.pecinovsky.english.lootp.canvasmanager.CanvasManager;
//%I-

import cz.pecinovsky.english.lootp.utility.NamedColor;
import cz.pecinovsky.english.lootp.utility.IO;
import cz.pecinovsky.english.lootp.utility.Position;
import cz.pecinovsky.english.lootp.utility.Size;

//%A+ >144
import java.util.ArrayList;
import java.util.List;

//%A-
//%X+ xxxxx Start of the ovejumped text with declaration of the envelope xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class Town_134_
{    private Town_134_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- End of the ovejumped text with declaration of the envelope -----


/*******************************************************************************
 * Instance třídy {@code Town} je singleton a představuje město,
 * do kterého budou postupně umísťovány různé objekty.
 * Town může být větší než aktuální plátno a umístí se vždy tak,
 * aby ve středu plátna bylo aktuální políčko, které lze nastavit.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
public class Town implements IPaintable
{
//== CONSTANT CLASS ATTRIBUTES =================================================

    /** Výchozí počet sloupců. */
    private static final int COLUMN_COUNT_0 = 10;

    /** Výchozí počet řádků. */
    private static final int ROW_COUNT_0 = 10;

    /** Správce plátna, v němž se město vyskytuje. */
    private static final CanvasManager CM = CanvasManager.getInstance();

    /** Jediná přípustná instance města. */
    private static final Town singleton = new Town(COLUMN_COUNT_0, ROW_COUNT_0);



//== VARIABLE CLASS ATTRIBUTES =================================================
//== STATIC CONSTRUCTOR (CLASS INITIALIZER, STATIC INICITALIZING BLOCK) ========
//== CONSTANT INSTANCE ATTRIBUTES ==============================================
//%A+ >144

    /** Seznam všech okruhů ve městě. */
    private final List<Ring> okruhy = new ArrayList<Ring>();



//%A-
//== VARIABLE INSTANCE ATTRIBUTES ==============================================

    /** Aktuální velikost kroku správce plátna. */
    private int module = CM.getStep();

    /** Rectangle zobrazující plochu města. */
    private Rectangle ground;

    /** Rectangle označující current políčko. */
    private Rectangle current;

    /** Aktuální počet sloupců města. */
    private int columnSize;

    /** Aktuální počet řádků města. */
    private int rowSize;

    /** Sloupec políčka, které se bude zobrazovat. */
    private int currentColumn;

    /** Řádek políčka, které se bude zobrazovat. */
    private int currentRow;



//== CLASS GETTERS AND SETTERS =================================================
//== OTHER NON-PRIVATE CLASS METHODS ===========================================

//##############################################################################
//== CONSTUCTORS AND FACTORY METHODS ===========================================

    /***************************************************************************
     * Vrátí (jedinou existující) instanci města.
     *
     * @return Požadovaná instance
     */
    public static Town getInstance()
    {
        return singleton;
    }


    /***************************************************************************
     * Vytvoří nové město se zadaným počtem sloupců a řádků.
     * Prozatím se nepočítá, že by se rozměr města v průběhu jeho života měnil.
     *
     * @param columnSize   Počet sloupců vytvářeného města
     * @param rowSize     Počet řádků vytvářeného města
     */
    private Town(int columnSize, int rowSize)
    {
        this.columnSize = columnSize;
        this.rowSize    = rowSize;

        currentColumn = this.columnSize / 2;
        currentRow    = this.rowSize / 2;

        ground  = new Rectangle(0, 0, 1, 1, NamedColor.SMOKY);
        current = new Rectangle(0, 0, 1, 1, NamedColor.MILKY);

        CM.add(this);
    }



//== ABSTRACT METHODS ==========================================================
//== INSTANCE GETTERS AND SETTERS ==============================================

    /***************************************************************************
     * Vrátí velikost modulu, tj. délku strany políčka města.
     *
     * @return Velikost modulu
     */
    public int getModule()
    {
        return module;
    }

//%A+ >=139z

    /***************************************************************************
     * Vrátí aktuální políčkový rozměr města, tj. počet jeho sloupců a řádků.
     *
     * @return Aktuální políčkový rozměr města
     */
    public Size getFieldSize()
    {
        return new Size(columnSize, rowSize);
    }

//%A-


//== OTHER NON-PRIVATE INSTANCE METHODS ========================================

    /***************************************************************************
     * Přestěhuje current pole do jiné pozice města
     * a tím automaticky přesune město na plátně tak,
     * aby bylo current pole opět uprostřed plátna.
//%I+ <139z
//     * Prozatím nekontroluje, zda pole vůbec zůstane po přesunu ve městě.
//%I-
//%A+ >=139z
     * Není-li nastavovaná pozice uvnitř města, vyhodí výjimku.
//%A-
     *
     * @param sloupec Nový sloupec aktivního pole
     * @param řádek   Nový řádek aktivního pole
     */
    public void aktivníNa(int sloupec, int řádek)
    {
//%A+ >=139z
        if ((sloupec < 0)  ||  (this.columnSize <= sloupec)  ||
            (řádek   < 0)  ||  (this.rowSize   <= řádek))
        {
            throw new IllegalArgumentException("Pozice mimo hranice města." +
                "\nSouřadnice musí být >=0, sloupec<" + columnSize +
                ", řádek<" +  rowSize +
                "\nByl však zadán sloupec=" + sloupec + ", řádek=" + řádek);
        }
//%A-
        currentColumn = sloupec;
        currentRow    = řádek;
        CM.redraw();
    }


    /***************************************************************************
     * Prostřednictvím dodaného kreslítka vykreslí obraz své instance.
     *
     * @param painter Painter, které nakreslí instanci
     */
    @Override
    public void paint(Painter painter)
    {
        module = CM.getStep();
        int canvasColumns = CM.getWidthInFields();
        int canvasRows    = CM.getHeightInFields();

        //Aktuální políčko města musí být uprostřed plátna
        int curColumn = canvasColumns / 2;
        int curRow    = canvasRows   / 2;

        //Position podkladu města se musí nastavit tak,
        //aby aktuální políčko bylo na plátně ve spočtené pozici
        int townX = (curColumn - currentColumn) * module;
        int townY = (curRow    - currentRow) * module;
        ground.setPosition(townX, townY);
        ground.setSize(columnSize*module, rowSize*module);

        ground.paint(painter);

        current.setPosition((2*curColumn - 1) * module / 2,
                            (2*curRow    - 1) * module / 2);
        current.setSize (2*module);
        current.paint(painter);
    }


            /***************************************************************************
             *
             */
            public void přidejVozidlo()
            {

            }



    /***************************************************************************
     * Přidá do města zadaný okruha na zadanou políčkovou pozici
     * a pokud se okruh do města nevejde, zvětší velikost města.
     * Kříží-li se přidávaný okruh s nějakým již existujícím okruhem,
     * umístí na danou křižovatku trafficLight.
     *
     * @param okruh   Přidávaný okruh
     * @param pPozice Políčková pozice přidávaného okruhu
     */
    public void přidejOkruh(Ring okruh, Position pPozice)
    {

    }


    /***************************************************************************
     * Vrací textovou reprezentaci (podpis) dané instance
     * používanou především k ladicím účelům.
     *
     * @return Požadovaná textová reprezentace
     */
    @Override
    public String toString()
    {
        return "Město_(" + new Size(columnSize, rowSize) +
               ", current-" + new Position(currentColumn, currentRow) + ")";
    }



//== PRIVATE AND AUXILIARY CLASS METHODS =======================================
//== PRIVATE AND AUXILIARY INSTANCE METHODS ====================================
//== EMBEDDED TYPES AND INNER CLASSES ==========================================
//== TESTING CLASSES AND METHODS ===============================================
//
//    /***************************************************************************
//     * Test method.
//     */
//    public static void test()
//    {
//        Town inst = new Town();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main(String[] args)  {  test();  }
    }

//%%- ---- Start of the ovejumped text with closing of the envelope ----
////////////////////////////////////////////////////////////////////////////////
//== TESTING CLASSES AND METHODS ===============================================

    /***************************************************************************
     * Test method.
     */
    public static void test()
    {
        final int ms = 500;
        CanvasManager CM = CanvasManager.getInstance();
        Town town = Town.getInstance();  IO.inform("Nové");
        CM.setStepAndSize(20, 12, 12);
        IO.inform("CM-20-12-12");
        town.aktivníNa(0, 0);
        IO.inform("m.akt(0,0)");
        town.aktivníNa(8, 8);              IO.inform("m.akt(8,8)");
        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main(String[] args)  {  test();  }
}
